package com.hnx.admin.aurora.utils;

import com.hnx.admin.aurora.web.json.TreeNode;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/*
创建人： 倔强的头发
创建时间：2025/6/18
功能描述:

*/
public class TreeUtil {
    private TreeUtil() {
        throw new UnsupportedOperationException("工具类不能实例化");
    }

    /**
     * 构建树形结构（默认根节点父ID为"0"）
     *
     * @param nodes       所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @return 构建好的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode> List<T> buildTree(List<T> nodes, Function<T, String> idExtractor) {
        return buildTree(nodes, idExtractor, "0", null);
    }

    /**
     * 构建树形结构（指定根节点父ID）
     *
     * @param nodes             所有节点列表
     * @param idExtractor       从节点中提取ID的函数
     * @param rootParentId      根节点的父ID值
     * @return 构建好的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode> List<T> buildTree(
            List<T> nodes,
            Function<T, String> idExtractor,
            String rootParentId) {
        return buildTree(nodes, idExtractor, rootParentId, null);
    }
    /**
     * 构建树形结构（带排序）
     *
     * @param nodes 所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @param comparator 节点比较器
     * @return 构建并排序后的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode> List<T> buildTree(
            List<T> nodes,
            Function<T, String> idExtractor,
            Comparator<T> comparator) {
        return buildTree(nodes, idExtractor, "0", comparator);
    }
    /**
     * 构建树形结构（完整参数）
     *
     * @param nodes 所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @param rootParentId 根节点的父ID值
     * @param comparator 节点比较器（可为null）
     * @return 构建好的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode> List<T> buildTree(
            List<T> nodes,
            Function<T, String> idExtractor,
            String rootParentId,
            Comparator<T> comparator) {
        // 参数校验
        validateParameters(nodes, idExtractor);

        // 空列表检查
        if (nodes.isEmpty()) {
            return Collections.emptyList();
        }
        // 按父ID分组建立索引（根据是否排序选择不同方式）
        Map<String, List<T>> parentIdToNodesMap = comparator == null
                ? nodes.stream().collect(Collectors.groupingBy(TreeNode::getParentId))
                : nodes.stream().sorted(comparator).collect(Collectors.groupingBy(TreeNode::getParentId));

        // 设置每个节点的子节点
        nodes.forEach(node -> {
            String nodeId = idExtractor.apply(node);
            List<T> children = parentIdToNodesMap.getOrDefault(nodeId, Collections.emptyList());
            node.setChildren(children);
        });

        // 返回根节点列表（根据是否排序选择不同方式）
        return comparator == null
                ? nodes.stream()
                .filter(node -> rootParentId.equals(node.getParentId()))
                .collect(Collectors.toList())
                : nodes.stream()
                .filter(node -> rootParentId.equals(node.getParentId()))
                .sorted(comparator)
                .collect(Collectors.toList());
    }
    /* ------------------------- 带映射转换的树构建方法 ------------------------- */
    /**
     * 构建树形结构并映射为另一种类型（默认根节点父ID为"0"）
     *
     * @param nodes 所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @param mapper 节点映射函数
     * @return 映射后的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode, U> List<U> buildTreeAndMap(
            List<T> nodes,
            Function<T, String> idExtractor,
            Function<T, U> mapper) {
        return buildTreeAndMap(nodes, idExtractor,  "0", null, mapper);
    }
    /**
     * 构建树形结构并映射为另一种类型（带排序）
     *
     * @param nodes 所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @param comparator 节点比较器
     * @param mapper 节点映射函数
     * @return 映射后的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode, U> List<U> buildTreeAndMap(
            List<T> nodes,
            Function<T, String> idExtractor,
            Comparator<T> comparator,
            Function<T, U> mapper) {
        return buildTreeAndMap(nodes, idExtractor,  "0", comparator, mapper);
    }
    /**
     * 构建树形结构并映射为另一种类型（完整参数）
     *
     * @param nodes 所有节点列表
     * @param idExtractor 从节点中提取ID的函数
     * @param rootParentId 根节点的父ID值
     * @param comparator 节点比较器（可为null）
     * @param mapper 节点映射函数
     * @return 映射后的树形结构
     * @throws IllegalArgumentException 如果参数不合法
     */
    public static <T extends TreeNode, U> List<U> buildTreeAndMap(
            List<T> nodes,
            Function<T, String> idExtractor,
            String rootParentId,
            Comparator<T> comparator,
            Function<T, U> mapper) {
        // 参数校验
        validateParameters(nodes, idExtractor);
        Objects.requireNonNull(mapper, "对象转换方法不能为空");

        // 空列表检查
        if (nodes.isEmpty()) {
            return Collections.emptyList();
        }
        if (comparator == null) {
            Map<String, List<T>> map = nodes.stream().collect(Collectors.groupingBy(T::getParentId));
            nodes.forEach(n -> {
                String apply = idExtractor.apply(n);
                n.setChildren((List<TreeNode>) map.get(apply));
            });
            return nodes.stream().filter(n -> n.getParentId().equals(rootParentId)).collect(Collectors.mapping(mapper, Collectors.toList()));
        }
        else {
            Map<String, List<T>> map = nodes.stream().sorted(comparator).collect(Collectors.groupingBy(T::getParentId));
            nodes.forEach(n -> {
                String apply = idExtractor.apply(n);
                n.setChildren((List<TreeNode>) map.get(apply));
            });
            return nodes.stream().filter(n -> n.getParentId().equals(rootParentId)).sorted(comparator).collect(Collectors.mapping(mapper, Collectors.toList()));
        }
    }
    /**
     * 验证参数有效性
     */
    private static <T extends TreeNode> void validateParameters(
            List<T> nodes,
            Function<T, String> idExtractor
    ) {
        Objects.requireNonNull(nodes, "数据列表不能为空");
        Objects.requireNonNull(idExtractor, "获取ID方法不能为空");

    }
    /**
     * 根据映射后的数据查找原始数据
     */
    private static <T extends TreeNode, U> T findOriginalData(List<T> originalList, U mappedData, Function<T, U> mapper) {
        return originalList.stream()
                .filter(item -> mapper.apply(item).equals(mappedData))
                .findFirst()
                .orElseThrow(() -> new IllegalStateException("Cannot find original data for mapped value"));
    }
}
